package Runde5;

public class ReplaceableTree<A extends Comparable<? super A>> extends Tree<A> {

	/**
	 * @precondition root != null
	 * @postcondition Creates a new tree with root labeled by given param
	 */
	public ReplaceableTree(A root) {
		super(root);
	}
	
	/**
	 * @precondition label != null
	 * @postcondition adds a new node with given label to the tree
	 */
	@Override
	public void add(A label) {
		List<Node> myList = new List<Node>();
		myList.add(root);
		Iter<Node> i = myList.iterator();
		boolean notFound = true;
		while (notFound) {
			Node currentNode = i.next();
			if (currentNode.getLeftChild() == null) {
				currentNode.setLeftChild(new Node(label));
				notFound = false;
			} else if (currentNode.getRightChild() == null) {
				currentNode.setRightChild(new Node(label));
				notFound = false;
			} else {
				myList.add(currentNode.getLeftChild());
				myList.add(currentNode.getRightChild());
			}
		}
		
	}
	
	/**
	 * @postcondition replaces a subtree on the given position with the given subtree
	 */
	public void replace(Iter<Boolean> position, Tree<? extends A> subTree) {
		Node parent = root;
		Node pos = root;
		boolean temp = false;
		boolean replaceRoot = true;
		try {
			while(position.hasNext()) {
				replaceRoot = false;
				temp = position.next();
				parent = pos;
				if(temp)
					pos = pos.getRightChild();
				else
					pos = pos.getLeftChild();
			}
			Node replace = createSubTree(subTree.root);
			if(replaceRoot)
				root = replace;
			else {
				if(temp)
					parent.setRightChild(replace);
				else
					parent.setLeftChild(replace);
			}
		} catch(Exception e) {}
	}
	
	/**
	 * @precondition node != null
	 * @postcondition copies the given node
	 */
	private Node createSubTree(Tree<? extends A>.Node node) {
		Node newNode = new Node(node.getLabel());
		if(node.getLeftChild() != null)
			newNode.setLeftChild(createSubTree(node.getLeftChild()));
		if(node.getRightChild() != null)
			newNode.setRightChild(createSubTree(node.getRightChild()));
		return newNode;
	}
	
	/**
	 * @precondition label != null
	 * @postcondition nodes are added to the iterator's list in levelorder
	 **/
	protected void addNodesToList(Node node, List<A> list) {
		List<Node> myList = new List<Node>();
		myList.add(node);
		Iter<Node> i = myList.iterator();
		while (i.hasNext()) {
			Node currentNode = i.next();
			list.add(currentNode.getLabel());
			if (currentNode.getLeftChild() != null) {
				myList.add(currentNode.getLeftChild());
			}
			if (currentNode.getRightChild() != null) {
				myList.add(currentNode.getRightChild());
			}
		}
	}
}
